package cn.com.cetccst.appstore.network;

import static cn.com.cetccst.appstore.kv.AppStoreKV.kvStore;
import static cn.com.cetccst.tools.device.Device.getOsv;

import android.content.Context;
import android.os.Build;
import android.text.TextUtils;

import androidx.annotation.NonNull;

import com.bumptech.glide.Glide;
import com.bumptech.glide.integration.okhttp3.OkHttpUrlLoader;
import com.bumptech.glide.load.model.GlideUrl;
import com.google.gson.JsonObject;

import java.io.IOException;
import java.io.InputStream;
import java.util.Map;

import cn.com.cetccst.appstore.kv.KVKeys;
import cn.com.cetccst.appstore.log.AppStoreLogger;
import cn.com.cetccst.appstore.network.response.AppListResponse;
import cn.com.cetccst.appstore.network.response.CategoryListResponse;
import cn.com.cetccst.network.BaseCallback;
import cn.com.cetccst.network.IRetrofitClient;
import cn.com.cetccst.network.RetrofitManager;
import cn.com.cetccst.network.log.IHttpLog;
import okhttp3.Interceptor;
import okhttp3.OkHttpClient;
import okhttp3.Request;
import okhttp3.Response;
import okhttp3.ResponseBody;
import retrofit2.Call;
import retrofit2.Retrofit;

public class AppStoreHttpRequester {
    private static final String MEDIA_JSON_TYPE = "application/json;charset=UTF-8";
    private static final String X_TOKEN = "Authorization";
    private static final String PACKAGE_NAME = "package";
    private static final String X_VERSION = "X-version";
    public static final String PROTO_VERSION = "5.4";
    public static final String API_VERSION_NAME = "version";
    public static final String OS_VERSION = "X-OSVersion";
    public static final String DEVICE_TYPE = "X-DType";
    public static final String BUILD_TYPE = "X-BuildType";
    private static IRetrofitClient retrofitClient;
    private static IAppStoreApiService apiService;
    private static AppStoreHttpRequester httpRequester;

    private AppStoreHttpRequester() {
    }

    public static void initialize(Context context, String baseUrl) {
        if (retrofitClient == null) {
            retrofitClient = new RetrofitManager.Builder(context, baseUrl)
                    .setLogLevel(IHttpLog.Level.BODY)
                    .addInterceptor(new Interceptor() {
                        @NonNull
                        @Override
                        public Response intercept(@NonNull Chain chain) throws IOException {
                            Request originalRequest = chain.request();
                            Request.Builder authorisedRequest = originalRequest.newBuilder();

                            //TODO token这块临时这么写，后续再优化
                            addHeaderIfNecessary(originalRequest, authorisedRequest, X_TOKEN, kvStore != null ? "Bearer " + kvStore.decodeString(KVKeys.KEY_MAM_TOKEN) : null);
                            addHeaderIfNecessary(originalRequest, authorisedRequest, PACKAGE_NAME, "com.zdk.mg.mgworkstore");
                            addHeaderIfNecessary(originalRequest, authorisedRequest, API_VERSION_NAME, PROTO_VERSION);
                            addHeaderIfNecessary(originalRequest, authorisedRequest, DEVICE_TYPE, Build.BRAND + "_" + Build.MODEL);
                            addHeaderIfNecessary(originalRequest, authorisedRequest, OS_VERSION, getOsv());
                            addHeaderIfNecessary(originalRequest, authorisedRequest, BUILD_TYPE, "du");

                            return chain.proceed(authorisedRequest.build());
                        }
                    })
                    .build();
            Retrofit retrofit = retrofitClient.getRetrofit();
            //配置Glide OKHTTP ssl
            Glide.get(context).getRegistry().replace(GlideUrl.class, InputStream.class, new OkHttpUrlLoader.Factory(AppStoreHttpRequester.getInstance().getOKHttpClient()));
            apiService = retrofit.create(IAppStoreApiService.class);
        }
    }

    public IHttpLog getHttpLogConfig() {
        return retrofitClient.getHttpLogConfig();
    }

    public OkHttpClient getOKHttpClient() {
        return retrofitClient.getOKHttpClient();
    }

    public static AppStoreHttpRequester getInstance() {
        if (httpRequester == null) {
            httpRequester = new AppStoreHttpRequester();
        }
        return httpRequester;
    }

    private static void addHeaderIfNecessary(Request orgRequest, Request.Builder newRequest, String headerName, String headerContent) {
        if (TextUtils.isEmpty(orgRequest.header(headerName)) && !TextUtils.isEmpty(headerContent)) {
            newRequest.header(headerName, headerContent);
        }
    }

    public void requestAllApps(Map<String, String> queryMap, BaseCallback<AppListResponse> callback) {
        if (apiService != null) {
            Call<AppListResponse> call = apiService.getAllApps(queryMap);
            call.enqueue(callback);
        }
    }

    public void requestCategoryList(Map<String, String> queryMap, BaseCallback<CategoryListResponse> callback) {
        if (apiService != null) {
            Call<CategoryListResponse> call = apiService.getCategoryNameByCategoryId(queryMap);
            call.enqueue(callback);
        }
    }

    public void requestAppDetail(@NonNull String appId, BaseCallback<JsonObject> callback) {
        if (apiService != null) {
            Call<JsonObject> call = apiService.getAppDetail(appId);
            call.enqueue(callback);
        }
    }

    public void requestPublisher(@NonNull String publisherId, BaseCallback<JsonObject> callback) {
        if (apiService != null) {
            Call<JsonObject> call = apiService.getPublisher(publisherId);
            call.enqueue(callback);
        }
    }

    /**
     * API 采用steaming对大文件进行下载，防止OOM
     *
     * @param url
     * @param start
     * @param callback
     */
    public void downLoadApk(final String url, final long start, final BaseCallback<ResponseBody> callback) {
        new Thread(() -> {
            getHttpLogConfig().addIgnoringBodyApi(url);
            Call<ResponseBody> call = apiService.downloadFile(url, "bytes=" + start + "-");
            try {
                retrofit2.Response<ResponseBody> response = call.execute();
                callback.onResponse(response.body());
            } catch (IOException e) {
                AppStoreLogger.error("download apk error ", e);
                callback.onResponse(null);
            }
            getHttpLogConfig().removeIgnoringBodyApi(url);
        }).start();
    }
}
